package com.nexgo.payment.aop;

import android.os.Handler;
import android.os.Looper;

import com.nexgo.payment.App;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by xiaox on 2018/1/9.
 */
@Aspect
public class RunOnThreadInjection {
    private Logger mLog;
    private Handler mHandler;

    RunOnThreadInjection() {
        mLog = LoggerFactory.getLogger("RunOnThreadInjection");
        mHandler = new Handler(Looper.getMainLooper());
    }

    /**
     * 返回void类型的方法
     */
    @Pointcut("execution(void *(..))")
    public void voidMethod() {

    }

    /**
     * 被@RunOnMainThread注解的方法
     */
    @Pointcut("@annotation(com.nexgo.payment.aop.annotation.RunOnMainThread)")
    public void annotationWithRunOnMainThread() {
    }

    /**
     * 被@RunOnWorkThread注解的方法
     */
    @Pointcut("@annotation(com.nexgo.payment.aop.annotation.RunOnWorkThread)")
    public void annotationWithRunOnWorkThread() {
    }

    @Around("annotationWithRunOnMainThread() && voidMethod()")
    public void runOnMainThreadProcess(ProceedingJoinPoint joinPoint) {
        postMainThread(new Runnable() {
            @Override
            public void run() {
                try {
                    mLog.debug("主线程运行,{}", joinPoint.getSignature().toString());
                    joinPoint.proceed();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            }
        });
    }

    @Around("annotationWithRunOnWorkThread() && voidMethod()")
    public void runOnWorkThreadProcess(ProceedingJoinPoint joinPoint) {
        postWorkThread(new Runnable() {
            @Override
            public void run() {
                try {
                    mLog.debug("工作线程运行,{},{}", joinPoint.getSignature().toString(), Thread.currentThread().getName());
                    joinPoint.proceed();
                } catch (Throwable throwable) {
                    throwable.printStackTrace();
                }
            }
        });
    }

    /**
     * 主线程运行
     *
     * @param runnable
     */
    private void postMainThread(Runnable runnable) {
        if (Looper.myLooper() == Looper.getMainLooper()) {
            runnable.run();
        } else {
            mHandler.post(runnable);
        }
    }

    /**
     * 工作线程运行
     *
     * @param runnable
     */
    private void postWorkThread(Runnable runnable) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            runnable.run();
        } else {
            App.sExecutor.execute(runnable);
        }
    }
}
